package com.chiyoyo.multipay.framework.core.client;

import com.chiyoyo.multipay.framework.core.client.dto.order.PayOrderNotifyReqDTO;
import com.chiyoyo.multipay.framework.core.client.dto.order.PayOrderRespDTO;
import com.chiyoyo.multipay.framework.core.client.dto.order.PayOrderUnifiedReqDTO;
import com.chiyoyo.multipay.framework.core.client.dto.refund.PayRefundRespDTO;
import com.chiyoyo.multipay.framework.core.client.dto.refund.PayRefundUnifiedReqDTO;
import com.chiyoyo.multipay.framework.core.client.dto.transfer.PayTransferRespDTO;
import com.chiyoyo.multipay.framework.core.client.dto.transfer.PayTransferUnifiedReqDTO;
import com.chiyoyo.multipay.framework.core.client.exception.PayException;
import com.chiyoyo.multipay.framework.core.enums.transfer.PayTransferTypeEnum;

import java.util.Map;

/**
 * @author chil
 * 支付客户端，用于对接各支付渠道的 SDK，实现发起支付、退款等功能
 */
public interface PayClient {

    /**
     * 获得渠道编码
     *
     * @return 渠道编码
     */
    String getChannelCode();

    /**
     * 获得第三方真实的client
     *
     * @param <ClientType> 第三方真实的client类型
     * @return 第三方真实的client
     */
    <ClientType> ClientType getRealClient();

    // ============ 支付相关 ============

    /**
     * 调用支付渠道进行统一下单操作
     *
     * @param reqDTO 下单请求信息，包含订单相关的参数
     * @return PayOrderRespDTO 支付订单响应信息，包含支付订单的结果
     */
    PayOrderRespDTO unifiedOrder(PayOrderUnifiedReqDTO reqDTO);

    /**
     * 解析订单通知的方法
     *
     * @param reqDTO 支付订单通知请求DTO
     * @return 解析后的订单响应信息
     * @throws IllegalArgumentException 如果参数params或body为null时抛出此异常
     * @throws PayException             如果解析订单通知过程中发生异常，将异常信息包装为PayException异常并抛出
     */
    PayOrderRespDTO parseOrderNotify(PayOrderNotifyReqDTO reqDTO);

    /**
     * 获取订单信息
     *
     * @param outTradeNo 外部订单号
     * @return PayOrderRespDTO 支付订单响应信息
     * @throws PayException 包装后的系统异常，当查询支付单出现异常时抛出
     */
    PayOrderRespDTO getOrder(String outTradeNo);

    // ============ 退款相关 ============

    /**
     * 执行统一退款操作
     *
     * @param reqDTO 退款请求DTO，包含退款相关信息
     * @return PayRefundRespDTO 退款响应DTO，包含退款结果信息
     * @throws PayException 当执行退款过程中出现异常时，将异常包装为PayException并抛出
     */
    PayRefundRespDTO unifiedRefund(PayRefundUnifiedReqDTO reqDTO);

    /**
     * 解析退款通知的响应数据
     *
     * @param params 退款通知的参数集合
     * @param body   退款通知的消息体
     * @return PayRefundRespDTO 退款响应信息
     * @throws PayException 如果解析退款通知失败，则抛出PayException异常
     */
    PayRefundRespDTO parseRefundNotify(Map<String, String> params, String body);

    /**
     * 根据外部订单号和外部退款号获取退款信息
     *
     * @param outTradeNo  外部订单号
     * @param outRefundNo 外部退款号
     * @return PayRefundRespDTO 退款响应信息
     * @throws PayException 如果在查询退款单过程中发生异常，则抛出此异常
     */
    PayRefundRespDTO getRefund(String outTradeNo, String outRefundNo);

    // ============ 转账相关 ============

    /**
     * 统一的转账接口
     *
     * @param reqDTO 统一支付转账请求DTO对象
     * @return PayTransferRespDTO 支付转账响应DTO对象
     * @throws PayException 当转账请求验证失败或转账过程中发生异常时抛出
     */
    PayTransferRespDTO unifiedTransfer(PayTransferUnifiedReqDTO reqDTO);

    /**
     * 根据订单号和转账类型获取转账单详情
     *
     * @param outTradeNo 外部订单号
     * @param type       转账类型
     * @return PayTransferRespDTO 转账单详情
     * @throws PayException 当查询转账单发生异常时抛出
     */
    PayTransferRespDTO getTransfer(String outTradeNo, PayTransferTypeEnum type);
}
